package cn.maihe.elg.operation.centers.hymake.handler.service;

import cn.maihe.elg.operation.centers.hymake.config.HyMakeInfoConfig;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.xm.XMBaseRespDTO;
import cn.maihe.elg.operation.centers.hymake.dto.handler.vo.xm.XMRevokeApplyReqDTO;
import cn.maihe.elg.operation.centers.hymake.enums.HyMakeCheckResultEnum;
import cn.maihe.elg.operation.centers.hymake.enums.HyMakeRespCodeEnum;
import cn.maihe.elg.operation.centers.hymake.exception.HyMakeException;
import cn.maihe.elg.operation.centers.hymake.handler.HyMakeCenterTradeService;
import cn.maihe.elg.operation.centers.supports.CenterTradeContext;
import cn.maihe.elg.operation.centers.supports.annotation.CenterTradeService;
import cn.maihe.elg.operation.model.enums.*;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.RevokeOrderAttachmentDO;
import cn.maihe.elg.operation.repository.entity.RevokeOrderInfo;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.RevokeOrderInfoService;
import cn.maihe.elg.operation.utils.CurrencyUpperUtil;
import cn.maihe.elg.operation.utils.ElgLogger;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.elg.operation.utils.StringUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Description 保函撤销申请
 * @Author caixh
 * @Date 2022/3/30.
 * 3.1.9、接收电子投标保函退保申请(文件)
 */
@CenterTradeService(
        provider = CenterProviderEnum.XIANMEN,
        centerNo = CenterNoEnum.XIAMEN,
        tradeType = TradeType.lstSurrend,
        reqClass = XMRevokeApplyReqDTO.class,
        respClass = XMBaseRespDTO.class
)
@Slf4j
public class XMRevokeApplyService extends HyMakeCenterTradeService<XMRevokeApplyReqDTO, XMBaseRespDTO> {

    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private RevokeOrderInfoService revokeOrderInfoService;

    public XMRevokeApplyService(HyMakeInfoConfig centerInfosConfig) {
        super(centerInfosConfig);
    }

    /**
     * 具体业务处理
     *
     * @param context
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public XMBaseRespDTO processService(CenterTradeContext<XMRevokeApplyReqDTO, XMBaseRespDTO> context) {

        XMRevokeApplyReqDTO req = context.getReq();
        Long centerId = context.getCenterId();
        Long orgId = context.getOrgId();
        String centerOrderId = req.getSurrenderInfo().getOrderNo();

        AcceptOrderInfoDO orderInfoDO = acceptOrderInfoService.getByCenterOrderId(centerId, orgId, centerOrderId);
        if (orderInfoDO == null) {

            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("查无此投保申请记录")
                    .build();
        }
        String revokeNo = orderInfoDO.getGuaranteeNo();
        RevokeFlagEnum flagEnum = RevokeFlagEnum.resolve(orderInfoDO.getRevokeFlag());
        if (flagEnum == RevokeFlagEnum.SUCCESS) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("退保状态为[" + flagEnum + "]，不能再申请退保")
                    .build();
        }
        if (flagEnum == RevokeFlagEnum.PROCESSING) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("退保审核中，请耐心等待审核结果")
                    .build();
        }
        if (flagEnum != RevokeFlagEnum.INIT && flagEnum != RevokeFlagEnum.FAILURE) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("退保状态不是待退保状态，不能申请退保")
                    .build();
        }

        if (orderInfoDO.getStatus() == AcceptOrderStatus.FINISH.getStatus()) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("保函已完成，不能退保申请")
                    .build();
        }
        if (orderInfoDO.getStatus() == AcceptOrderStatus.CANCEL.getStatus()) {
            return XMBaseRespDTO.builder()
                    .success(false)
                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
                    .errorDesc("保函已取消，不能退保申请")
                    .build();
        }
        if (orderInfoDO.getStatus() != AcceptOrderStatus.HAS_OUT_GUARANTEE.getStatus() && orderInfoDO.getStatus() != AcceptOrderStatus.REVOKE_FAIL.getStatus()) {
//            return XMBaseRespDTO.builder()
//                    .success(false)
//                    .errorCode(HyMakeCheckResultEnum.FAILURE.getCheckResult())
//                    .errorDesc("已出函状态才能发起退保，未出函前可调用放弃投保申请")
//                    .build();
        }

        XMRevokeApplyReqDTO.SurrenderInfo surrenderInfo = req.getSurrenderInfo();


        AcceptOrderInfoDO updateOrderInfo = AcceptOrderInfoDO.builder().id(orderInfoDO.getId())
                .status(AcceptOrderStatus.REVOKE_PROCESSING.getStatus())
                .revokeFlag(RevokeFlagEnum.PROCESSING.getFlag())
//                .remark(req.getBackReasonDetail())
                .remark(surrenderInfo.getReason())
                .build();
//        acceptOrderInfoService.updateById(updateOrderInfo);

        ProjectInfoDO project = projectInfoService.selectById(orderInfoDO.getProjectId());

        RevokeOrderInfo revokeOrderInfo = RevokeOrderInfo.builder()
                .id(IdGenerate.getId())
                .centerId(centerId)
                .orgId(orgId)
                //通过保函编号关联受理订单号
                .revokeNo(revokeNo)
                .note(surrenderInfo.getReason())
                //备注字段存储 业务流水号
                // todo 参数无法确定
//                .remark(req.getPolicyNo())
                .projectCode(project.getProjectCode()).projectName(orderInfoDO.getProjectName())
                .sectionCode(project.getSectionCode()).sectionName(orderInfoDO.getSectionName())
                .tenderer(project.getTenderer()).status(0)
                // todo 参数无法确定
//                .bankName(req.getBankName())
                .accountName(surrenderInfo.getBankAccount())
                .openBankName(surrenderInfo.getBankOpenbank())
                .bankCardNum(surrenderInfo.getBankCode())
                .backPremium(orderInfoDO.getGuaranteeFee())
//                .backPremium(req.getBackPremium()==null?0L:(new BigDecimal(req.getBackPremium()).multiply(new BigDecimal("100")).longValue()))
                .build();

        // todo 退保申请的文件流附件暂时不处理
        List<RevokeOrderAttachmentDO> attachmentDOS = null;
        if (req.getFilesInfo() != null) {
            AtomicInteger index = new AtomicInteger(1);
            attachmentDOS = req.getFilesInfo().stream().map(item -> {
                return RevokeOrderAttachmentDO.builder()
                        .revokeOrderId(revokeOrderInfo.getId())
                        .no(index.getAndIncrement())
                        // todo 参数无法确定, 对方传输的是文件流，如何保存本地？
//                        .fileUrl(item.getBackFileUrl())
                        .fileName(item.getFilename())
                        .fileMd5(item.getFilemd5())
                        .build();
            }).collect(Collectors.toList());
        }

        revokeOrderInfoService.saveRevokeOrderInfo(revokeOrderInfo, attachmentDOS, updateOrderInfo);

        return XMBaseRespDTO.builder()
                .success(true)
                .build();
    }

    @Override
    protected XMRevokeApplyReqDTO buildReq(Map<String, Object> clearParams) {
        try {
//            ElgLogger.debug(log, l -> l.debug("项目退保申请请求原文：{}", clearParams));
//            String jsonString = JSONObject.toJSONString(clearParams);
            ElgLogger.debug(log, l -> l.debug("项目退保申请请求原文：{}", clearParams.toString()));
            String jsonString = toJsonString(clearParams);
            ElgLogger.debug(log, l -> l.debug("项目退保申请请求jsonString：{}", jsonString));
//            String clearString = jsonString.replace("\\\"", "\"")
//                    .replace("\"[", "[")
//                    .replace("]\"", "]")
//                    .replace("\"{", "{")
//                    .replace("}\"", "}");
            String clearString = jsonString.replace("\\\"", "\"")
                    .replace("\\\\\"", "\"")
                    .replace("\"[", "[")
                    .replace("]\"", "]")
                    .replace("\"{", "{")
                    .replace("}\"", "}");
            ElgLogger.debug(log, l -> l.debug("项目退保申请请求clearString：{}", clearString));

            return JSONObject.parseObject(clearString, this.reqClass);
        } catch (Exception e) {
            throw HyMakeException.of(HyMakeRespCodeEnum.FAILURE, "反序列化异常", e);
        }
    }
}
